#include "qplaintexteditappender.h"
#include <QMetaObject>
#include <QThread>
#include <QRegularExpression>
#include <QTextCharFormat>

LogHighlighter::LogHighlighter(QTextDocument *parent)
    : QSyntaxHighlighter(parent)
{
    // 初始化默认颜色（可通过外部动态修改）
    m_levelColors[LogLevel::Debug] = QColor(0x00,0xA0,0x00);    // Debug：绿色（适中亮度，避免刺眼）
    m_levelColors[LogLevel::Info] = QColor(0x00,0x66,0xCC);     // Info：蓝色（柔和蓝，清晰可见）
    m_levelColors[LogLevel::Warning] = QColor(0xFF,0xD7,0x00);  // Warning：黄色（暖黄，醒目不刺眼）
    m_levelColors[LogLevel::Error] = QColor(0xFF,0x33,0x33);    // Error：红色（稍暗红色，避免视觉疲劳）
    m_levelColors[LogLevel::Fatal] = QColor(0x99,0x00,0xCC);    // Fatal：紫色（亮紫，突出致命错误）
}

void LogHighlighter::setLevelColor(LogLevel level, const QColor &color)
{
    m_levelColors[level] = color;
    rehighlight();  // 重新高亮所有文本
}

void LogHighlighter::highlightBlock(const QString &text)
{
    // 正则表达式：匹配 "[级别]" 格式（不区分大小写）
    static const QRegularExpression regex(R"(\[(Debug|Info|Warning|Error|Fatal)\])",
                                          QRegularExpression::CaseInsensitiveOption);

    QRegularExpressionMatchIterator it = regex.globalMatch(text);
    while (it.hasNext())
    {
        QRegularExpressionMatch match = it.next();
        QString levelStr = match.captured(1);  // 获取匹配的级别字符串（如"Debug"）

        // 转换为LogLevel枚举
        LogLevel level = LogLevel::Debug;
        if (levelStr.compare("Info", Qt::CaseInsensitive) == 0)
            level = LogLevel::Info;
        else if (levelStr.compare("Warning", Qt::CaseInsensitive) == 0)
            level = LogLevel::Warning;
        else if (levelStr.compare("Error", Qt::CaseInsensitive) == 0)
            level = LogLevel::Error;
        else if (levelStr.compare("Fatal", Qt::CaseInsensitive) == 0)
            level = LogLevel::Fatal;

        // 应用对应颜色
        QTextCharFormat format;
        format.setForeground(m_levelColors[level]);
        setFormat(match.capturedStart(), match.capturedLength(), format);
    }
}






QPlainTextEditAppender::QPlainTextEditAppender(LogLevel level, QPlainTextEdit *widget)
    : BaseAppender(level),
    m_widget(nullptr),
    m_highlighter(nullptr),
    m_maxLines(1000),  // 默认最大1000行
    m_currentLines(0)
{
    if (widget)
        setWidget(widget);  // 关联组件并初始化高亮器
}

void QPlainTextEditAppender::setWidget(QPlainTextEdit *widget)
{
    QMutexLocker locker(&m_mutex);
    m_widget = widget;
    if (m_widget)
    {
        m_widget->setReadOnly(true);  // 日志组件通常设为只读
        // 初始化高亮器（绑定到组件的文档）
        m_highlighter = new LogHighlighter(m_widget->document());
    }
    else
    {
        delete m_highlighter;
        m_highlighter = nullptr;
    }
}

void QPlainTextEditAppender::setLevelColor(LogLevel level, const QColor &color)
{
    QMutexLocker locker(&m_mutex);
    if (m_highlighter)
        m_highlighter->setLevelColor(level, color);
}

void QPlainTextEditAppender::setMaxLines(int maxLines)
{
    QMutexLocker locker(&m_mutex);
    m_maxLines = maxLines;
}

void QPlainTextEditAppender::append(LogLevel level, const QString &msg)
{
    // 1. 级别过滤：低于当前级别不处理
    if (level < m_level)
        return;

    // 2. 检查组件是否有效
    QMutexLocker locker(&m_mutex);
    if (!m_widget)
        return;

    // 3. 复制参数到局部变量（避免跨线程访问问题）
    QString logMsg = msg;
    QPlainTextEdit* widget = m_widget;
    int currentLines = m_currentLines;
    int maxLines = m_maxLines;

    // 4. 线程安全：如果当前线程不是UI线程，通过元对象系统调用
    if (QThread::currentThread() != widget->thread())
    {
        QMetaObject::invokeMethod(this, "doAppend",
                                  Qt::QueuedConnection,
                                  Q_ARG(QString, logMsg),
                                  Q_ARG(int, currentLines),
                                  Q_ARG(int, maxLines));
    }
    else
    {
        // 直接在UI线程执行
        doAppend(logMsg, currentLines, maxLines);
    }
}

void QPlainTextEditAppender::doAppend(const QString &msg, int currentLines, int maxLines)
{
    QMutexLocker locker(&m_mutex);
    if (!m_widget)
        return;

    // 检查是否超过最大行数：超过则清空
    if (maxLines > 0 && currentLines >= maxLines)
    {
        m_widget->clear();
        m_currentLines = 0;  // 重置行数计数
    }

    // 追加日志并滚动到底部
    m_widget->appendPlainText(msg);
    m_widget->moveCursor(QTextCursor::End);  // 自动滚动到最新日志

    // 更新行数计数
    m_currentLines++;
}
